<h1>day05 npm与包</h1>

<h2>1.回顾(模块化开发)</h2>

<ul><li><p>概念：按照commonjs规范，定义的公共数据</p></li><li><p>好处：有了规范，代码复用高，易维护，减少沟通成本，有利于团队协会</p></li><li><p>模块化开发的种类：自定义模块，内置模块，第三方模块</p></li><li><p>==自定义模块(开发者按commonjs规范，自己写的js文件)==</p><p>~~~js
1.创建模块化文件
2.在这个模块化文件中定义公共数据
3.暴露数据
exports.属性名 = 属性值 (不推荐使用，适用于单个数据暴露)
module.exports = { 数据 } (推荐使用，直观方便)
4.使用
在业务代码中引入：require(&quot;./或../开头&quot;)
~~~</p><p>==注意：不要混用，混用最后还是暴露module.exports中的数据==</p></li><li><p>内置模块</p><ul><li><p>==fs==</p></li><li>URL</li><li>querystring：parse,stringify  操作查询字符串    user=12&amp;pass=13</li><li><p>==path : parse(),basename(),extname(),join()==</p></li></ul></li><li><p>第三方模块</p><ul><li><p>第三方模块需要通过npm下载使用</p></li></ul></li></ul>

<h2>2.npm与包</h2>

<h3>2.1 包介绍</h3>

<ul><li><p>概念</p><p>Node.js中的第三方模块又叫做包。就像电脑和计算机指的是同一个事物，第三方模块和包指的是同一个概念，只不过叫法不同。</p><p>npm主要内容有：</p><p>​	==(1)包管理工具== </p><p>​       ==(2)npm社区==</p></li><li><p>包来源</p><p>包是由第三方个人或团队开发出来的，免费供给所有开发者使用。npm社区https://www.npmjs.com/。</p></li><li><p>包的特点</p><ul><li><p>在Node.js中，如果只用内置模块或开发者自己定义模块开发，效率会很低。所以就有了第3方包</p></li><li><p>包是基于内置模块( commonjs规范 )封装出来的，提供了更高级、更方便的API，==极大的提高了开发效率==</p></li><li><p>包和模块之间的关系，类似于Jquery和原生js之间的关系</p></li><li><p>要想称为一个包除了遵守模块化规范以外，还要遵守包的一些规范，如：说明文档，协议说明等。</p><p><img alt="image-20210511160354647" src="img\image-20210511160354647.png"/></p></li></ul></li></ul>

<h3>2.3 包管理工具npm</h3>

<h4>2.3.1 查看npm</h4>

<ul><li><p>==包管理工具==指的是安装node环境后，==自动安装了npm工具==。Node Package Manager，简称 npm 包管理工具。</p></li><li><p>查看版本</p><p>~~~js
npm -v
显示版本信息，安装成功 -- 6.9.0
~~~</p></li></ul>

<h4>2.3.2 第一次 安装包的说明</h4>

<ul><li>初次装包完成后，在项目文件夹下多一个==node_modules的文件夹和package-lock.json的配置文件==</li><li>node_modules文件夹用来存放所有已安装到项目中的第三方包。==require()导入==第三方包时，就是从这个目录中查找并加载</li><li>package-lock.json配置文件用来记录node_modules目录下的每一个包的下载信息，例如包的名字、版本号、下载地址等</li><li>开发者不要手动修改node_modules或package-lock.json文件中的任何代码，npm包管理工具会自动维护它们</li></ul>

<h4>2.3.3 版本介绍</h4>

<ul><li><p>第1位数字：表示大版本号，一般当软件整体重写，或出现不向后兼容的改变时，增加此位，此位是0时表示软件还在开发阶段。</p></li><li><p>第2位数字：表示功能更新，出现新功能时增加此位</p></li><li><p>第3位数字：表示小修改，如修复bug，只要有修改就增加此位</p></li><li><p>苹果手机系统 @13</p><p>~~~js
v0.0.1   测试
V1.0.0   发布
V2.0.0   软件整体重写，或出现不向后兼容的改变时
V2.2.1 ----&gt;V2.3.1  功能更新
V2.3.1 ----&gt;V2.3.2  如修复bug
~~~</p></li></ul>

<h4>2.3.4 查看文档（npm社区）</h4>

<p><img alt="1670550482809" src="C:\Users\ibm\AppData\Roaming\Typora\typora-user-images\1670550482809.png"/></p>

<h4>==2.3.5 npm常用命令==</h4>

<ul><li><p>==install命令(下载)==</p><p>~~~js
npm install/i 包名  (默认下载最新版本)
npm install/i 包名@版本号  (下载指定版本的包)  注意：最后最后保留一个版本，最后下载的那个版本
npm install/i 包名1 包名2 ...  （同时下载多个包）</p><p>npm install/i 包名 -S / --save <br/>npm install/i 包名 -D /--save--dev<br/>~~~</p></li><li><p>uninstall(删除)</p><p>~~~js
npm uninstall/r 包名
~~~</p></li><li><p>init</p><p>~~~js
npm init -y  (建议使用)  会自动创建package.json文件
注意：
	1.文件夹名不要有中文，空格
  2.项目文件夹名要用内置模块和第三方模块名称
npm init     【一问一答的形式】
~~~</p></li></ul>

<h3>2.4 淘宝镜像</h3>

<h4>2.4.1 淘宝镜像介绍</h4>

<p><img alt="2-10淘宝镜像" src="img\2-10淘宝镜像.png"/></p>

<h4>2.4.2 配置淘宝镜像</h4>

<ul><li><p>第一种：全局安装cnpm工具（ 我们npm工具如何使用的，cnpm一模一样 ）</p><ul><li><p>第一步在命名行执行以下命令</p><p>~~~js
npm install -g cnpm --registry=https://registry.npm.taobao.org
~~~</p></li><li><p>查看是否配置成功</p><p><img alt="1670553041391" src="C:\Users\ibm\AppData\Roaming\Typora\typora-user-images\1670553041391.png"/></p></li><li><p>使用和npm下载是一样的用法</p><p>~~~js
cnpm i 包名
~~~</p></li></ul></li><li><p>第二种：配置nmp命令的源：在任意目录下执行一次即可(建议使用)</p><ul><li><p>第一步在命令行执行以下命令</p><p>~~~js
npm config set registry https://registry.npm.taobao.org
~~~</p></li><li><p>查看是否配置成功</p><p><img alt="1670552690897" src="C:\Users\ibm\AppData\Roaming\Typora\typora-user-images\1670552690897.png"/></p></li><li><p>使用</p><p>~~~js
npm i 包名
~~~</p></li></ul></li></ul>

<h3>2.5 package.json</h3>

<p>==有无package.json和package-lock.json都不影响程序正常执行。没有node_modules会影响 。==</p>

<ul><li><p>简介</p><p>按照规范：在项目根目录中，必须提供一个叫做 package.json 的包管理配置文件。</p><p>==叫项目管家，是记录你的npm下载包的信息==</p></li><li><p>开发问题</p><p><img alt="团队开发的问题" src="img\团队开发的问题.png"/></p></li><li><p>==package.json的使用步骤==</p><p>~~~js
1.创建一个package.json文件  (package.json不能是空文件)
2.在项目中下载需要的包，下载的包信息会自动存储在package.json的dependencies中
npm i 包名  会自动记录在package.json的dependencies中
npm i 包名 --save / -S  ： 完整写法
npm i 包名 --save--dev  / -D   会自动记录在package.json的的devDependencies</p><p>3.项目中传递代码，node<em>modules文件删除没有关系，只要package.json文件在就可以
npm i (下载package.json中记录的所有的包)
4.在git上传数据，node</em>modules文件忽略（.gitignore把node_modules文件夹忽略）
~~~</p></li><li><p>==标准package.json的创建==</p><p>~~~js
npm init -y  (建议使用)  会自动创建package.json文件
注意：
	1.文件夹名不要有中文，空格
  2.项目文件夹名要用内置模块和第三方模块名称
npm init     【一问一答的形式】
~~~</p></li><li><p>完整属性表</p><p>| 属性名                             | 说明                     |
| ---------------------------------- | ------------------------ |
| name                               | 包（项目）的名称         |
| version                            | 包（项目）的版本号       |
| description                        | 包（项目）的描述         |
| ==main==                           | 包（项目）入口文件       |
| ==scripts==(到项目中可以讲到)      | 定义快捷脚本命令         |
| keywords                           | 项目关键词               |
| author                             | 作者                     |
| license                            | 协议                     |
| ==dependencies==                   | 包（项目）依赖的模块     |
| ==devDependencies==( webpack再说 ) | 包（项目）开发依赖的模块 |</p></li></ul>

<h3>2.6 总结</h3>

<ul><li>后期写项目<ul><li>第一步 npm init -y    （创建一个项目管家，管理项目，package.json)</li><li>下载包，写业务逻辑  </li><li>项目传递 （省略node_modules文件夹）</li><li>其他人运行：先执行npm i (根据项目管家中记录包，下载所有需要的依赖包)</li></ul></li></ul>

<h2>3.包与加载机制</h2>

<h3>3.1 包分类</h3>

<ul><li>包分为项目包和全局包</li></ul>

<h4>3.1.1 项目包</h4>

<ul><li>==被安装到项目的node_modules目录中的包，都是项目包== </li><li>项目包又分为两类：<ul><li>开发依赖包：被记录到devDependencies节点中的包，只在开发期间会用到(在写代码的时候用)<ul><li>webpack打包工具</li><li>测试工具日志</li></ul></li><li>核心依赖包：被记录到dependencies节点中的包，在开发期间和项目上线之后都会用到。</li></ul></li></ul>

<h4>3.1.2 全局包</h4>

<ul><li><p>==工具类==的包称为全局包，使用的时候npm一样，在cmd命令行使用的，并不是在代码文件中引入的。</p></li><li><p>安装命令：</p><p><code>js
npm i 包名 -g (global全局)
</code></p></li><li><p>使用特点：</p><ul><li><p>并不是在代码文件中引入的，全局包像npm一样当作可执行程序进行使用</p></li><li>决定某个包是否需要全局安装，需要参考官方提供的使用说明书</li><li><p>全局包会被安装到C:\Users\用户目录\AppData\Roaming\npm\node_modules目录下</p></li></ul></li><li><p>例：markdown</p><p><code></code>`js</p><p><code></code>`</p></li></ul>

<h3>2.2 包加载机制（总结）</h3>

<h4>1.2.1 内置模块的加载机制</h4>

<ul><li><p>内置模块是由Node.js官方提供的模块，==内置模块的加载优先级最高==。</p></li><li><p>例如，<strong>require(&#39;fs&#39;) </strong>始终返回内置的fs模块，即使在node_modules目录下有名字相同的包也叫做fs，也会引入核心的内置fs模块</p></li><li><p>所以第三方模块（npm上搜索不到内置模块）和自定义模块不要起官网已有的模块名称</p><p><code></code>`js</p><p><code></code>`</p></li></ul>

<h4>1.2.2 自定义模块加载机制</h4>

<ul><li><p>使用require()加载自定义模块时，==必须指定以./或../==开头的路径标识符。</p></li><li><p>如果没有指定<strong>./或../</strong>这样的路径标识符，则Node.js会把它当作<strong>内置模块</strong>或<strong>第三方模</strong>块进行加载。</p></li><li><p>==自定义模块不要放在node_modules中,不要和内置模块重名==。</p></li><li><p>在使用require()导入自定义模块时，如果省略了文件的扩展名，则Node.js会按顺序分别尝试加载以下的文件：</p><ul><li><p>文件名.js扩展名进行加载</p></li><li><p>文件名.json扩展名进行加载</p></li><li><p>加载失败，终端报错<strong>Error:Cannot find module &#39;xxx&#39;</strong></p><p><code></code>`js</p><p><code></code>`</p></li></ul></li></ul>

<h4>1.2.3 第三方模块加载机制</h4>

<ul><li><p>如果require()的模块标识符不是内置模块，也没有以‘./’或‘../’开头，则Node.js会从当前模块的父目录开始，尝试从当前文件夹的/node_modules文件夹中加载第三方模块。</p></li><li><p>如果没有找到对应的第三方模块，则移动到再上一层父目录中，进行加载，直到当前项目文件的盘符根目录。</p></li><li><p>==总结：一定是把第三方模块下载到  根项目下的 node<em>modules ，且项目中只有根项目下有 node</em>modules==</p><p><code></code>`js</p><p><code></code>`</p></li></ul>

<h3>2.3 package.json中的main属性</h3>

<ul><li><p>main属性，可以指定模块加载的主入口文件，当引入模块时用文件夹名结尾时生效。有三种加载方式：</p><ul><li><p>根据目录下的package.json的文件，寻找main属性指定的文件名，作为require()加载的入口。</p></li><li><p>如果目录里没有package.json文件，或者main入口不存在，则Node.js将会加载目录下的index.js文件（所以目录中的默认入口为index.js）。</p></li><li><p>如果以上两步都加载失败，则Node.js会在终端打印错误消息，报告模块缺失：Error:Cannot find module &#39;xxx&#39;</p><p><code></code>`js
//在文件省略的情况下，以package.json中main属性定义的文件为主（默认index.js)</p><p>//指定了main就以指定的文件为准
//main指定的文件没有，则去引入index.js
let m2 = require(&quot;./modules/m2&quot;);
console.log(m2);
<code></code>`</p></li></ul></li></ul>
